package node;

import grammar.Lexer;
import lexical.Key;
import node.decl.ConstDecl;
import node.decl.VarDecl;
import node.func.FuncDef;
import node.func.MainFuncDef;
import symbol.SymbolTable;

import java.util.ArrayList;

public class CompUnit implements Node{
    private final Lexer lexer;
    private final SymbolTable table;
    private final Node father = null;
    public ArrayList<Node> decls = new ArrayList<>();
    public ArrayList<Node> funcs = new ArrayList<>();
    public Node mainFunc = null;

    public CompUnit(Lexer lexer, SymbolTable table) {
        this.lexer = lexer;
        this.table = table;
        parseCompUnit();
    }

    public void parseCompUnit() {
        while ((lexer.isWordType(0, Key.CONSTTK)) ||
                (lexer.isWordType(0, Key.INTTK) && lexer.isWordType(1, Key.IDENFR) && !(lexer.isWordType(2, Key.LPARENT)))) {
            if (lexer.isWordType(0, Key.CONSTTK) && lexer.isWordType(1, Key.INTTK)) {
                decls.add(new ConstDecl(lexer, table, this));
            } else if (lexer.isWordType(0, Key.INTTK)) {
                decls.add(new VarDecl(lexer, table, this));
            }
        }
        while ((lexer.isWordType(0, Key.VOIDTK)) ||
                (lexer.isWordType(0, Key.INTTK) && !(lexer.isWordType(1, Key.MAINTK)))) {
            funcs.add(new FuncDef(lexer, table, this));
        }
        if (lexer.isWordType(0, Key.INTTK) && lexer.isWordType(1, Key.MAINTK)) {
            mainFunc = new MainFuncDef(lexer, table, this);
        }
    }

    @Override
    public Node getFather() {
        return father;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (Node decl : decls) {
            sb.append(decl.toString());
        }
        for (Node func : funcs) {
            sb.append(func.toString());
        }
        sb.append(mainFunc.toString());
        return sb.append("<CompUnit>").toString();
    }

    @Override
    public String genMidCode() {
        for (Node decl : decls) {
            decl.genMidCode();
        }
        for (Node func : funcs) {
            func.genMidCode();
        }
        mainFunc.genMidCode();
        return "";
    }

}
